//---------------------------------------------------------------------------
#include "sample_http.h"
#include <windows.h>

sample_http::sample_http() {
        http_lib        = NULL;
        http_socket     = NULL;
        http_lib        = new sckt::Library;
        http_socket     = new sckt::TCPSocket;
        CookieEnable    = true;
        HeaderEnable    = false;
        RedirectEnable  = false;
}

sample_http::~sample_http() {
        /*try {
                http_socket->Close();
        }
        catch(sckt::Exc &exception) {}
        */
        if (http_lib) delete http_lib;
        if (http_socket) delete http_socket;
}

std::string sample_http::Get(std::string url) {
        //---Clear Temp data--
        ClearData();
        //-------
        int url_len = url.length();
        std::string uri;
        std::string send_header;
        std::string recv_data;
        std::string result;
        http_url = url;

        if (url_len == 0) {
                return result;
        }
        if (!ChekProto(url)) {
                return result;
        }

        uri = GetUri(url);

        if (!Connect(uri,80)) {
                return result;
        }

        send_header = MakeHeader(url);

        if (!SendData(send_header)) {
                return result;
        }
        if (!RecvData(recv_data)) {
                return result;
        }

        Disconnect();
        ParseHeader(recv_data);

        if (RedirectEnable) {
                if (http_redirect_url.length() > 0) {
                        recv_data = this->Get(http_redirect_url);
                }
        }

        result = recv_data;

        return result;
}

std::string sample_http::Post(std::string url, http_postdata pd) {
        //---Clear Temp data--
        ClearData();
        //-------
        int url_len = url.length();
        std::string uri;
        std::string send_header;
        std::string recv_data;
        std::string result;
        http_url = url;

        if (url_len == 0) {
                return result;
        }
        if (!ChekProto(url)) {
                return result;
        }

        uri = GetUri(url);

        if (!Connect(uri,80)) {
                return result;
        }

        send_header = MakePostheader(url,pd);

        if (!SendData(send_header)) {
                return result;
        }
        if (!RecvData(recv_data)) {
                return result;
        }

        Disconnect();
        ParseHeader(recv_data);

        if (RedirectEnable) {
                if (http_redirect_url.length() > 0) {
                        recv_data = this->Post(http_redirect_url,pd);
                }
        }

        result = recv_data;

        return result;
}

//------Private Function

bool sample_http::Connect(std::string uri,int port) {
        try {
                http_ip = http_lib->GetHostByName(uri.c_str(),port);
        }
        catch(sckt::Exc &exception) {
                return false;
        }
        try {
                http_socket->Open(http_ip);
        }
        catch(sckt::Exc &exception) {
                return false;
        }
        return true;
}

void sample_http::Disconnect() {
        try {
                http_socket->Close();
        }
        catch(sckt::Exc &exception) { }
}

void sample_http::ClearData() {
        http_header.clear();
        http_redirect_url.clear();
        http_url.clear();
        http_result_code = 0;
}

bool sample_http::ChekProto(std::string url) {
        int pos;
        bool result = false;
        std::string proto;

        pos = url.find("://",0);
        if (pos != -1) {
                proto = url.substr(0,pos);
                if (proto.compare("http") == 0) {
                        result = true;
                }
        }
        
        return result;
}

std::string sample_http::GetUri(std::string url) {
        std::string uri;
        int pos;
        url.erase(0,7);
        pos = url.find("/");
        if (pos == -1) {
                url.append("/");
                pos = url.length()-1;
        }
        uri = url.substr(0,pos);
        return uri;
}

std::string sample_http::MakeHeader(std::string url) {
        //TODO: Make HeaderClass
        std::string result;
        int url_len = url.length();
        char *buf = new char[url_len+100];
        wsprintf(buf,"GET %s HTTP/1.0\r\n",url);
        result.append(buf);
        result.append("Accept: text/html, */*;q=0.1\r\n");
        result.append("Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1\r\n");
        result.append("User-Agent: Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.62\r\n");
        if (CookieEnable) {
                std::string CookieStr = cookie.make_str();
                if (!CookieStr.empty()) {
                        result.append("Cookie: ");
                        result.append(CookieStr);
                        result.append("\r\n");
                }
        }
        result.append("Connection: close\r\n\r\n");
        delete [] buf;
        return result;
}

std::string sample_http::MakePostheader(std::string url, http_postdata pd) {
        //TODO: Make HeaderClass
        std::string result;
        std::string postdata = pd.make_str();
        int postdata_len = postdata.length();
        int url_len = url.length();
        char *buf = new char[url_len+100];
        wsprintf(buf,"POST %s HTTP/1.0\r\n",url);
        result.append(buf);
        result.append("Accept: text/html, */*;q=0.1\r\n");
        result.append("Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1\r\n");
        result.append("User-Agent: Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.62\r\n");
        if (CookieEnable) {
                std::string CookieStr = cookie.make_str();
                if (!CookieStr.empty()) {
                        result.append("Cookie: ");
                        result.append(CookieStr);
                        result.append("\r\n");
                }
        }
        result.append("Content-Type: application/x-www-form-urlencoded\r\n");
        wsprintf(buf,"Content-Length: %d\r\n", postdata_len);
        result.append(buf);
        result.append("Connection: close\r\n\r\n");
        result.append(postdata);
        delete [] buf;
        return result;
}

bool sample_http::SendData(std::string data) {
        bool result = false;
        const char *pData = data.c_str();
        int iDataLen = lstrlen(pData);
        try {
              http_socket->Send((sckt::byte *)pData,iDataLen);
              result = true;
        }
        catch(sckt::Exc &exception) {}
        return result;
}

bool sample_http::RecvData(std::string &recv_data) {
        bool result = false;
        char *recv_buf = new char[256];
        try {
                while( http_socket->Recv((sckt::byte *)recv_buf,255) ) {
                        recv_data.append(recv_buf);
                }

                result = true;
        }
        catch(sckt::Exc &exception) {}
        delete [] recv_buf;

        return result;
}

void sample_http::ParseHeader(std::string &recv_data) {
        int pos = -1;
        pos = recv_data.find("\r\n\r\n",0);
        if (pos != -1) {
                http_header = recv_data.substr(0,pos+4);
                http_result_code = get_result_code(http_header);
                
                if (CookieEnable) {
                        cookie.ParseHeader(http_header);
                }

                if (RedirectEnable) {
                        FindRedirect(http_header);
                }

                if (!HeaderEnable) {
                        recv_data.erase(0,pos+4);
                }
        }
}

void sample_http::FindRedirect(std::string header) {
        std::string Temp;
        int pos = header.find("Location: ",0);
        if (pos != -1) {
                Temp = header;
                Temp.erase(0,pos+10);
                pos = Temp.find("\r\n",0);
                if (pos != -1) {
                        http_redirect_url = Temp.substr(0,pos);
                        if (http_redirect_url[0] == '/') {
                                http_redirect_url.insert(0,http_url);
                        }
                }
        }
}

int sample_http::get_result_code(std::string content) {
     int result = 0;
     int pos = content.find("HTTP/1.");
     if (pos != -1) {
        std::string buf  = content.substr(9,3);
        result = atoi(buf.c_str());
     }
     return result;
}
